#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/epoll.h>

#include "./include/tcp.server.h"
#include "./include/sql.h"
#define MAX_SIZE 1024

int main(int argc, char **argv)
{
    if (argc != 3)
    {
        printf("Please input ip and prot!\n");
        goto err;
    }

    int sockfd;
    int cfd;
    int r_len;
    int fd;
    int epfd;
    int n_num;
    int num = find_exist;

    char sql[1024];
    char ip[20] = {0};
    int port = atoi(argv[2]);

    strcpy(ip, argv[1]);

    create_tab("account");   // 创建用户注册表
    create_tab("online");    // 创建用户登录表
    init_sqlite3("contact"); // 创建联系人表

    struct epoll_event *my_event;
    struct epoll_event r_event[MAX_SIZE];
    struct sockaddr_in client_addr;
    socklen_t len = sizeof(struct sockaddr_in);

    online user;

    if ((sockfd = create_tcp_server(ip, port)) == -1)
    {
        perror("sockfd create error!");
        goto err;
    }

    if ((epfd = epoll_create1(0)) == -1)
    {
        printf("epoll create error!\n");
        goto err;
    }

    my_event = (struct epoll_event *)malloc(sizeof(struct epoll_event));
    my_event->events = EPOLLIN;
    my_event->data.fd = sockfd;
    epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, my_event);

    while (1)
    {
        n_num = epoll_wait(epfd, r_event, MAX_SIZE, -1);
        for (int i = 0; i < n_num; i++)
        {
            if ((r_event[i].data.fd == sockfd) && (r_event[i].events == EPOLLIN))
            {
                if ((cfd = accept(sockfd, (struct sockaddr *)&client_addr, &len)) == -1)
                {
                    perror("accept error!");
                    goto err;
                }
                printf("client ip = %s port = %d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

                set_nonblock(cfd);
                my_event = (struct epoll_event *)malloc(sizeof(struct epoll_event));
                my_event->events = EPOLLIN | EPOLLET;
                my_event->data.fd = cfd;

                epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, my_event);
            }
            else
            {
                if (r_event[i].events == EPOLLIN)
                {
                    fd = r_event[i].data.fd;
                    memset(&user, 0, sizeof(online));
                    while (1)
                    {
                        if ((r_len = recv(fd, &user, sizeof(online), 0)) == -1)
                        {
                            if (errno == EAGAIN)
                            {
                                break;
                            }
                            else
                            {
                                perror("recv error!");
                                goto err;
                            }
                        }

                        if (r_len == 0)
                        {
                            printf("client is close!\n");
                            my_event = (struct epoll_event *)malloc(sizeof(struct epoll_event));
                            my_event->data.fd = fd;
                            epoll_ctl(epfd, EPOLL_CTL_DEL, fd, my_event);

                            // memset(sql, 0, sizeof(sql));
                            // sprintf(sql, "delete from online where user='%s';", user.use);
                            // sqlite_grop(sql);

                            shutdown(fd, SHUT_RDWR);
                            break;
                        }
                        else if (r_len > 0)
                        {           
                            strcpy(user.passwd,rc4_encrypt(user.passwd));
                            switch (user.signal)
                            {
                            case REGISTER:
                            {
                                num = find_exist;
                                memset(sql, 0, sizeof(sql));
                                sprintf(sql, "select user from account where user='%s'", user.use);
                                num = find_tab(sql, find_exist,fd);
                                if (exist == num)
                                {
                                    user.signal = ERROR; // 用户存在，将标志位置为-1回给客户端；
                                    send(fd, &user, sizeof(online), 0);
                                }
                                else if (find_exist == num)
                                {
                                    user.signal = REGISTER; // 用户不存在，将标志位置为1回给客户端
                                    memset(sql, 0, sizeof(sql));
                                    sprintf(sql, "insert into account(user, passwd)values('%s', '%s');", user.use, user.passwd);

                                    sqlite_grop(sql); // 执行sql语句，创建用户
                                    send(fd, &user, sizeof(online), 0);
                                }
                                break;
                                // int num;
                                // char sql[1024] = {0};

                                // sprintf(sql, "SELECT COUNT(*) FROM sqlite_master where type ='table' and name = '%s'", user->use);
                                // num = find_tab(sql);
                                // if (num > 0)
                                // {
                                //     user->signal = -1; // 用户已存在，将标志位置为-1；
                                //     send(fd, user, sizeof(online), 0);
                                // }
                                // else
                                // {
                                //     init_sqlite3(user->use); // 用户不存在数据库表中，进行创建
                                //     user->signal == 1;       // 创建成功后将标志位置为1；
                                //     send(fd, user, sizeof(online), 0);
                                // }
                            }
                            case LOGIN:
                            {
                                num = find_exist;
                                memset(sql, 0, sizeof(sql));
                                sprintf(sql, "select user,passwd from account where user='%s' and passwd='%s';", user.use, user.passwd);
                                num = find_tab(sql, find_exist, fd);
                                if (exist == num) // 用户或者密码匹配到了，signal置位发送给客户端
                                {
                                    memset(sql, 0, sizeof(sql));
                                    sprintf(sql, "select user from online where user='%s';", user.use);
                                    num = 0;
                                    num = find_tab(sql, find_exist, fd);
                                    if (find_exist == num)
                                    {
                                        user.signal = LOGIN;
                                        memset(sql, 0, sizeof(sql));
                                        send(fd, &user, sizeof(online), 0);
                                        //sprintf(sql, "insert into online(user, passwd)values('%s', '%s');", user.use, user.passwd);
                                        // 将用户名插入到登录表中，判断用户是否在线
                                        //sqlite_grop(sql);
                                        //send(fd, &user, sizeof(online), 0);
                                    }
                                    else if (exist == num)
                                    {
                                        user.signal = ALR_LOG;
                                        send(fd, &user, sizeof(online), 0);
                                    }
                                }
                                else if (find_exist == num) // 用户名或密码匹配不到，siganl置位发送给客户端
                                {
                                    user.signal = ERROR;
                                    send(fd, &user, sizeof(online), 0);
                                }
                                break;
                            }
                            case ADD:
                            {
                                memset(sql, 0, sizeof(sql));
                                sprintf(sql, "select name from contact where name='%s';", user.name);
                                num = find_exist;
                                num = find_tab(sql, find_exist, fd);
                                if (find_exist == num)
                                {
                                    memset(sql, 0, sizeof(sql));
                                    sprintf(sql, "insert into contact(name, age, tel, addr, mailbox)values('%s', '%d', '%s', '%s', '%s');", user.name, user.age, user.tel, user.addr, user.mailbox);
                                    sqlite_grop(sql);
                                    
                                    memset(&user, 0, sizeof(online));
                                    user.signal = ADD;
                                    send(fd, &user, sizeof(online), 0);
                                }                               
                                else if (exist == num)
                                {
                                    memset(&user, 0, sizeof(online));
                                    user.signal = ALR_LOG;
                                    send(fd, &user, sizeof(online), 0);
                                }
                                break;
                            }
                            case SEE:
                            {
                                memset(sql, 0, sizeof(sql));
                                strcpy(sql, "select * from contact");
                                memset(&user, 0, sizeof(online));
                                find_tab(sql, find_result, fd);

                                memset(&user, 0, sizeof(online));//查询结果发送给客户端后，再次置为signal，告诉客户端查询结束
                                user.signal = EXIT;
                                send(fd, &user, sizeof(online), 0);
                                break;
                            }
                            case SEARCH:
                            {
                                memset(sql, 0, sizeof(sql));
                                sprintf(sql, "select name from contact where name='%s';", user.name);
                                num = find_exist;
                                
                                num = find_tab(sql, find_exist, fd);
                                if (exist == num)
                                {
                                    printf("user exist\n");
                                    sprintf(sql, "select * from contact where name='%s';", user.name);
                                    find_tab(sql, find_result, fd);
                                    // memset(&user, 0, sizeof(online));
                                    // user.signal = SEARCH;
                                    // send(fd, &user, sizeof(online), 0);
                                }
                                else if (find_exist == num)
                                {
                                    printf("user no exist\n");
                                    memset(&user, 0, sizeof(online));
                                    user.signal = ERROR;
                                    send(fd, &user, sizeof(online), 0);
                                }
                                break;
                            }
                            case DELETE:
                            {
                                memset(sql, 0, sizeof(sql));
                                sprintf(sql, "delete from contact where name='%s';", user.name);
                                if (sqlite_grop(sql) == 0)
                                {
                                    user.signal = DELETE;
                                    send(fd, &user, sizeof(online), 0);
                                }
                                break;
                            }
                            case UPDATE:
                            {
                                memset(sql, 0, sizeof(sql));
                                sprintf(sql, "update contact set name='%s', age='%d', tel='%s', addr='%s', mailbox='%s' where name='%s';", user.name, user.age, user.tel, user.addr, user.mailbox, user.name);
                                if (sqlite_grop(sql) == 0)
                                {
                                    user.signal = UPDATE;
                                    send(fd, &user, sizeof(online), 0);
                                }
                                break;
                            }
                            default:
                            {
                                break;
                            }
                            }
                        }
                    }
                }
            }
        }
    }
err:
    return 0;
}